#include "CPqueue.hpp"
#include "caculator.hpp"

#include <vector>
#include <string>

#include <ctime>

std::vector<std::pair<char, func>> kv;

const int KVSIZE = 4;

void* Productor(void* arg)
{
    CPqueue<Calculator>* pq = (CPqueue<Calculator>*)arg;
    while(1)
    {
        int task = rand() % KVSIZE;
        func fun = kv[task].second;
        int x = rand() % 200;
        int y = rand() % 500;
        std::cout << pthread_self() << " productor send task ::[" << task << "]-->   " << x << (kv[task].first) << y << '=' << '?' << std::endl;

        pq->PushData(Calculator(x, y, fun));
        sleep(1);
    }
}

void* Consumer(void* arg)
{
    CPqueue<Calculator>* pq = (CPqueue<Calculator>*)arg;

    while(1)
    {
        Calculator tmp;
        pq->PopData(tmp);
        std::cout << pthread_self() << " consumer get task ::" << tmp() << std::endl;
    }
}

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid() ^ 0x323424);
    func MyAdd = [](int x, int y){ return x + y; };
    func MySub = [](int x, int y){ return x - y; };
    func MyMul = [](int x, int y){ return x * y; };
    func MyDiv = [](int x, int y){ return x / y; };

    kv.push_back(std::pair<char, func>('+', MyAdd));
    kv.push_back(std::pair<char, func>('-', MySub));
    kv.push_back(std::pair<char, func>('*', MyMul));
    kv.push_back(std::pair<char, func>('/', MyDiv));

    CPqueue<Calculator>* pq = new CPqueue<Calculator>(4);

    // 消费者线程
    pthread_t consumerThread[2];
    // 生产者线程
    pthread_t productorThread[2];

    // 消费者线程初始化
    pthread_create(&consumerThread[0], nullptr, Consumer, (void*)pq);
    sleep(1);
    pthread_create(&consumerThread[1], nullptr, Consumer, (void*)pq);
    sleep(1);
    // 生产者线程初始化
    pthread_create(&productorThread[0], nullptr, Productor, (void*)pq);
    sleep(1);
    pthread_create(&productorThread[1], nullptr, Productor, (void*)pq);
    sleep(1);

    pthread_join(consumerThread[0], nullptr);
    pthread_join(consumerThread[1], nullptr);
    pthread_join(productorThread[0], nullptr);
    pthread_join(productorThread[1], nullptr);

    delete pq;
    return 0;
}